#include "tcpserver.h"
#include "ui_tcpserver.h"
#include<QHostInfo>
#include<QMessageBox>
#include<QDateTime>
#include<QProcess>
#include<QDataStream>
#include<QFont>
#include<QDebug>
#include<QApplication>

TcpServer::TcpServer(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TcpServer),localFile(nullptr),tcpServer(nullptr)
                         ,clientConnection(nullptr)
{
    ui->setupUi(this);
    tcpPort = 6666;                                                     // 端口号
    tcpServer = new QTcpServer(this);                            // 监听套接字

    // 当有新的连接时，发出newConnection()信号
    connect(tcpServer,SIGNAL(newConnection()),
            this,SLOT(sendMessage()));

    // 初始化服务器
    initServer();
}

TcpServer::~TcpServer()
{
    delete ui;
}

void TcpServer::initServer()
{
    payloadSize = 64 * 1024;        // 每次发送数据的大小
    TotalBytes = 0;                 // 总共需要发送的数据大小
    bytestoWrite = 0;               // 剩余数据大小
    bytesWritten = 0;               // 已经发送数据大小
    ui->serverStatusLabel->setText(tr("请选择要传送的文件"));
    ui->progressBar->reset();
    ui->serverOpenBtn->setEnabled(true);
    ui->serverSendBtn->setEnabled(false);

    // 关闭服务器
    tcpServer->close();
    //localFile = new QFile(fileName);
}

void TcpServer::sendMessage()
{
    qDebug () << "TCP的链接已建立" ;
    ui->serverSendBtn->setEnabled(false);

    // 传送文件名等信息
    clientConnection = tcpServer->nextPendingConnection();

    // 当连接成功时，发出connected()信号
    connect(clientConnection,SIGNAL(bytesWritten(qint64)),
            this,SLOT(updateClientProgress(qint64)));
    ui->serverStatusLabel->setText(tr("开始传送文件:\n %1!").arg(theFileName));

    // 发送文件
    localFile = new QFile(fileName);
    if(! localFile->open(QFile::ReadOnly))
    {
        QMessageBox::warning(this,tr("应用程序"),tr("无法读取文件 %1:\n%2").arg(fileName)
                             .arg(localFile->errorString()));
        return ;
    }

    // 获取文件大小
    TotalBytes = localFile->size();

    // 构造一个数据流
    time.start();
    // 发送总大小信息，文件名大小信息，文件名
    QDataStream sendOut(&outBlock,QIODevice::WriteOnly);
    // 设置数据流的版本，客户端和服务器端使用的版本要相同
    sendOut.setVersion(QDataStream::Qt_4_0);
    // qDebug() << "文件名" <<  theFileName ;
    time.start();

    // 获取文件名
    const QString currentFile = fileName.right(fileName.size() - fileName.lastIndexOf('/')-1);
    // 将文件信息填入数据流
    sendOut << qint64(0) <<qint64(0) <<currentFile;

    // 这里的总大小是文件名大小等信息和实际文件大小的总和
    TotalBytes += outBlock.size();
    sendOut.device()->seek(0);

    // 返回outBolck的开始，用实际的大小信息代替两个qint64(0)空间
    sendOut << TotalBytes << qint64((outBlock.size() - sizeof(qint64)*2));

    // 发送完头数据后剩余数据的大小
    bytestoWrite = TotalBytes - clientConnection->write(outBlock);
    outBlock.resize(0);
}

void TcpServer::updateClientProgress(qint64 numBytes)
{
    // 已经发送数据的大小
    qApp->processEvents();
    bytesWritten += static_cast<int>(numBytes);
    if(bytestoWrite > 0)
    {
        // 如果还有数据要发送
        outBlock = localFile->read(qMin(bytestoWrite,payloadSize));
        // 发送完一次数据后还剩余数据的大小
        bytestoWrite -= static_cast<int>(clientConnection->write(outBlock));
        // 清空发送缓冲区
        outBlock.resize(0);
    }
    else
    {
        localFile->close();
    }
    ui->progressBar->setMaximum(TotalBytes);
    ui->progressBar->setValue(bytesWritten);

    const float useTime = time.elapsed();       // 传输时间
   // qDebug() << "uerTime:" << useTime;
    const double speed = bytesWritten / useTime;// 传输速度

    ui->serverStatusLabel->setText(tr("已发送 %1MB( %2MB/s)"
                                      "\n共%3MB 已用时:%4秒\n估计剩余时间:%5秒")
                                   .arg(bytesWritten / (1024*1024))
                                   .arg(speed * 1000 /(1024*1024),0,'f',2)
                                   .arg(TotalBytes /(1024*1024))
                                   .arg(useTime/1000,0,'f',0)
                                   .arg(TotalBytes/speed/1000 - useTime/1000,0,'f',0));
    // 发送完毕 关闭文件和套接字
    if(bytesWritten == TotalBytes)
    {
        localFile->close();
        tcpServer->close();
        ui->serverStatusLabel->setText(tr("传送文件: %1成功").arg(theFileName));
    }
}

void TcpServer::on_serverOpenBtn_clicked()
{
    // 获取要发送的文件
    fileName = QFileDialog::getOpenFileName(this);
    if(!fileName.isEmpty()) {
        // 获取文件信息
        theFileName = fileName.right(fileName.size()-fileName.lastIndexOf('/')-1);
        // qDebug() << "文件名" <<  theFileName ;
        ui->serverStatusLabel->setText(tr("要发送的文件为:%1").arg(theFileName));
        ui->serverSendBtn->setEnabled(true);
        ui->serverOpenBtn->setEnabled(false);
    }
}

void TcpServer::on_serverSendBtn_clicked()
{
    // 如果没有指定文件，弹出警告对话框
    if(! tcpServer->listen(QHostAddress::Any,tcpPort))
    {
        qDebug() << tcpServer->errorString()<<"ni好吧";
        close();
        return ;
    }
    ui->serverSendBtn->setEnabled(false);
    ui->serverStatusLabel->setText(tr("等待对方的接受......"));

    // 发送文件名
    emit sendFileName(theFileName);
}

// 关闭服务器
void TcpServer::on_serverCloseBtn_clicked()
{
    //qDebug() << "关闭" ;
    if(tcpServer->isListening())
    {
        qDebug() << "点击了关闭按钮";
        tcpServer->close();
        if(localFile->isOpen())
        {
            localFile->close();
        }
        clientConnection->abort();
    }
    close();
    ui->~TcpServer();
}

// 拒绝接收文件
void TcpServer::refused()
{
    tcpServer->close();
    ui->serverStatusLabel->setText(tr("对方拒绝接受!!!"));
}

void TcpServer::closeEvent(QCloseEvent *)
{
    on_serverCloseBtn_clicked();
}